home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #2 / Monster Media No. 2 (Monster Media)(1994).ISO / prog_bas / mquery.zip / MQUERY.BAS < prev    next >
BASIC Source File  |  1994-05-24  |  28KB  |  938 lines

  1. '------------------------------------------------------------
  2. ' VISDATA.BAS
  3. ' support functions for the Visual Data sample application
  4. '
  5. ' General Information: This app is intended to demonstrate
  6. '   and exercise all of the functionality available in the
  7. '   VT (Virtual Table) Object layer in VB 3.0 Pro.
  8. '
  9. '   Any valid SQL statement may be sent via the Utility SQL
  10. '   function excluding "select" statements which may be
  11. '   executed from the Dynaset Create function. With these
  12. '   two features, this simple app becomes a powerful data
  13. '   definition and query tool accessing any ODBC driver
  14. '   available at the time.
  15. '
  16. '   The app has the capability to perform all DDL (data
  17. '   definition language) functions. These are accessed
  18. '   from the "Tables" form. This form accesses the
  19. '   "NewTable", "AddField" and "IndexAdd" forms to do
  20. '   the actual table, field and index definition.
  21. '   Tables and Indexes may be deleted when the corresponding
  22. '   "Delete" button is enabled. It is not possible to
  23. '   delete fields.
  24. '
  25. ' Naming Conventions:
  26. '   "f..."   = Form
  27. '   "c..."   = Form control
  28. '   "F..."   = Form level variable
  29. '   "gst..." = Global String
  30. '   "gf..."  = Global flag (true/false)
  31. '   "gw..."  = Global 2 byte integer value
  32. '
  33. '------------------------------------------------------------
  34.  
  35. Option Explicit
  36.  
  37. 'api declarations
  38. Declare Function GetPrivateProfileString Lib "Kernel" (ByVal lpApplicationName As String, ByVal lpKeyname As String, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Integer, ByVal lpFileName As String) As Integer
  39. Declare Function WritePrivateProfileString Lib "Kernel" (ByVal lpApplicationName As String, ByVal lpKeyname As String, ByVal lpstring As String, ByVal lplFileName As String) As Integer
  40. Declare Function GetWindowsDirectory Lib "Kernel" (ByVal lpBuffer As String, ByVal nSize As Integer) As Integer
  41.  
  42. 'global object variables
  43. Global gCurrentDB As Database
  44. Global gfDBOpenFlag As Integer
  45. Global gCurrentDS As Dynaset
  46. Global gCurrentTbl As Table
  47. Global gCurrentQueryDef As QueryDef
  48. Global gCurrentField As Field
  49. Global gCurrentIndex As Index
  50. Global gTableListSS As Snapshot
  51.  
  52. 'global database variables
  53. Global gstDataType As String
  54. Global gstDBName As String
  55. Global gstUserName As String
  56. Global gstPassword As String
  57. Global gstDataBase As String
  58. Global gstDynaString As String
  59. Global gstTblName As String
  60. Global gfUpdatable As Integer
  61. Global glQueryTimeout As Long
  62. Global glLoginTimeout As Long
  63. Global gstTableDynaFilter As String
  64. Global gTblname As String ' used for filter and sort in grid and dynaset
  65. 'other global vars
  66. Global gstZoomData As String
  67. Global gwMaxGridRows As Long
  68. Global gWindowsDirectory As String
  69. Global gSQLUser As String
  70.  
  71. 'new field properties
  72. Global gwFldType As Integer
  73. Global gwFldSize As Integer
  74. Global gsumcolwid As Integer
  75. 'global find values
  76. Global gfFindFailed As Integer
  77. Global gstFindExpr As String
  78. Global gstFindOp As String
  79. Global gstFindField As String
  80. Global gfFindMatch As Integer
  81. Global gfFromTableView As Integer
  82.  
  83.  ' global filter values
  84. Global gFilterStr As String
  85.  
  86.  ' global sort values
  87. Global gSortStr As String
  88.  
  89.   ' Global flag for stored queries
  90. Global gStoredFlag As Integer
  91.  
  92. 'global seek values
  93. Global gstSeekOperator As String
  94. Global gstSeekValue As String
  95.  
  96. 'global flags
  97. Global gfDBChanged As Integer
  98. Global gfFROMSQL As Integer
  99. Global gfTransPending As Integer
  100. Global gfAddTableFlag As Integer
  101.  
  102. 'global constants
  103. Global Const DEFAULTDRIVER = "SQL Server"
  104. Global Const MODAL = 1
  105. Global Const HOURGLASS = 11
  106. Global Const DEFAULT_MOUSE = 0
  107. Global Const YES = 6
  108. Global Const MSGBOX_TYPE = 4 + 48 + 256
  109. Global Const TRUE_ST = "True"
  110. Global Const FALSE_ST = "False"
  111. Global Const EOF_ERR = 626
  112. Global Const FTBLS = 0
  113. Global Const FFLDS = 1
  114. Global Const FINDX = 2
  115. Global Const MAX_GRID_ROWS = 31999
  116. Global Const MAX_MEMO_SIZE = 20000
  117. Global Const GETCHUNK_CUTOFF = 50
  118. Global Const MB_YESNOCANCEL = 3
  119. Global Const MB_YESNO = 4
  120. Global Const MB_ICONSTOP = 16
  121. Global Const MB_ICONQUESTION = 32
  122. Global Const MB_ICONEXCLAMATION = 48
  123. Global Const MB_ICONINFORMATION = 64
  124. Global Const MB_DEFBUTTON2 = 256
  125. Global Const IDYES = 6
  126. Global Const IDNO = 7
  127. ' Define other.
  128.  
  129.  
  130.  
  131.  
  132. 'field type constants
  133. Global Const FT_TRUEFALSE = 1
  134. Global Const FT_BYTE = 2
  135. Global Const FT_INTEGER = 3
  136. Global Const FT_LONG = 4
  137. Global Const FT_CURRENCY = 5
  138. Global Const FT_SINGLE = 6
  139. Global Const FT_DOUBLE = 7
  140. Global Const FT_DATETIME = 8
  141. Global Const FT_STRING = 10
  142. Global Const FT_BINARY = 11
  143. Global Const FT_MEMO = 12
  144.  
  145. 'table type constants
  146. Global Const DB_TABLE = 1
  147. Global Const DB_ATTACHEDTABLE = 6
  148. Global Const DB_ATTACHEDODBC = 4
  149. Global Const DB_QUERYDEF = 5
  150. Global Const DB_SYSTEMOBJECT = &H80000002
  151.  
  152. 'dynaset option parameter constants
  153. Global Const VBDA_DENYWRITE = &H1
  154. Global Const VBDA_DENYREAD = &H2
  155. Global Const VBDA_READONLY = &H4
  156. Global Const VBDA_APPENDONLY = &H8
  157. Global Const VBDA_INCONSISTENT = &H10
  158. Global Const VBDA_CONSISTENT = &H20
  159. Global Const VBDA_SQLPASSTHROUGH = &H40
  160.  
  161. 'db create/compact constants
  162. Global Const DB_CREATE_GENERAL = ";langid=0x0809;cp=1252;country=0"
  163. Global Const DB_VERSION10 = 1
  164.  
  165. ' Microsoft Access QueryDef types
  166. Global Const DB_QACTION = &HF0
  167. Global Const DB_QCROSSTAB = &H10
  168. Global Const DB_QDELETE = &H20
  169. Global Const DB_QUPDATE = &H30
  170. Global Const DB_QAPPEND = &H40
  171. Global Const DB_QMAKETABLE = &H50
  172.  
  173. ' Index Attributes
  174. Global Const DB_UNIQUE = 1
  175. Global Const DB_PRIMARY = 2
  176. Global Const DB_PROHIBITNULL = 4
  177. Global Const DB_IGNORENULL = 8
  178. Global Const DB_DESCENDING = 1  'For each field in Index
  179.  
  180. Function ActionQueryType (qn As String) As String
  181.   Dim i As Integer
  182.  
  183.   gTableListSS.MoveFirst
  184.   While gTableListSS.EOF = False And gTableListSS!Name <> qn
  185.     gTableListSS.MoveNext
  186.   Wend
  187.   If gTableListSS!Name = qn Then
  188.     Select Case gTableListSS!Attributes
  189.       Case DB_QCROSSTAB
  190.         ActionQueryType = "Cross Tab"
  191.       Case DB_QDELETE
  192.         ActionQueryType = "Delete"
  193.       Case DB_QUPDATE
  194.         ActionQueryType = "Update"
  195.       Case DB_QAPPEND
  196.         ActionQueryType = "Append"
  197.       Case DB_QMAKETABLE
  198.         ActionQueryType = "Make Table"
  199.     End Select
  200.   Else
  201.     ActionQueryType = ""
  202.   End If
  203.  
  204. End Function
  205.  
  206. Sub ExecSql ()
  207.    Dim RetSQL As Long
  208.    If Not gStoredFlag Then ' flag goes here
  209.    If fQuery!cCriteria = "" Then ' no sql statment
  210.    gfFROMSQL = False
  211.    Exit Sub
  212.    End If
  213.    Else
  214.        gfFROMSQL = False
  215.         ResetMouse fQuery
  216.         MsgBar "", False
  217.         'gStoredFlag = False
  218.         If fQuery!Option1(0) = False Then
  219.          Dim dsform1 As New fDynaset
  220.          dsform1.Show
  221.         Else
  222.          Dim dsform2 As New fGridFrm
  223.          dsform2.Show
  224.        End If
  225.  
  226.    Exit Sub
  227.    End If
  228.    MsgBar "Executing SQL Statement", True
  229.    'SetHourGlass Me
  230.    If UCase(Mid(fQuery!cCriteria, 1, 6)) = "SELECT" And InStr(UCase(fQuery!cCriteria), " INTO ") = 0 Then
  231.      On Error GoTo SQLDSErr
  232. MakeDynaset:
  233.      gfFROMSQL = True
  234.      'create a new dynaset form
  235.      gstDynaString = ""
  236.     On Error GoTo SQLDSErr
  237.        If fQuery!Option1(0) = False Then
  238.          Dim dsform3 As New fDynaset
  239.          dsform3.Show
  240.        Else
  241.          Dim dsform4 As New fGridFrm
  242.          dsform4.Show
  243.        End If
  244.      On Error GoTo SQLErr
  245.  
  246.    End If
  247.  
  248.    GoTo SQLEnd
  249.  
  250. SQLErr:
  251.    If Err = 3065 Then   'row returning so try to create dynaset
  252.      Resume MakeDynaset
  253.    End If
  254.    ShowError
  255.    Resume SQLEnd
  256.  
  257. SQLDSErr:
  258.    Resume SQLEnd
  259.  
  260. SQLEnd:
  261.    ResetMouse fQuery
  262.    MsgBar "", False
  263.  
  264. End Sub
  265.  
  266. Function GetFieldType (ft As String) As Integer
  267.   'return field length
  268.   If ft = "String" Then
  269.     GetFieldType = FT_STRING
  270.   Else
  271.     Select Case ft
  272.       Case "Counter"
  273.         GetFieldType = FT_LONG
  274.       Case "True/False"
  275.         GetFieldType = FT_TRUEFALSE
  276.       Case "Byte"
  277.         GetFieldType = FT_BYTE
  278.       Case "Integer"
  279.         GetFieldType = FT_INTEGER
  280.       Case "Long"
  281.         GetFieldType = FT_LONG
  282.       Case "Currency"
  283.         GetFieldType = FT_CURRENCY
  284.       Case "Single"
  285.         GetFieldType = FT_SINGLE
  286.       Case "Double"
  287.         GetFieldType = FT_DOUBLE
  288.       Case "Date/Time"
  289.         GetFieldType = FT_DATETIME
  290.       Case "Binary"
  291.         GetFieldType = FT_BINARY
  292.       Case "Memo"
  293.         GetFieldType = FT_MEMO
  294.     End Select
  295.   End If
  296.  
  297. End Function
  298.  
  299. Function GetFieldWidth (t As Integer)
  300.   'determines the form control width
  301.   'based on the field type
  302.   Select Case t
  303.     Case FT_TRUEFALSE
  304.       GetFieldWidth = 850
  305.     Case FT_BYTE
  306.       GetFieldWidth = 650
  307.     Case FT_INTEGER
  308.       GetFieldWidth = 900
  309.     Case FT_LONG
  310.       GetFieldWidth = 1100
  311.     Case FT_CURRENCY
  312.       GetFieldWidth = 1800
  313.     Case FT_SINGLE
  314.       GetFieldWidth = 1800
  315.     Case FT_DOUBLE
  316.       GetFieldWidth = 2200
  317.     Case FT_DATETIME
  318.       GetFieldWidth = 2000
  319.     Case FT_STRING
  320.       GetFieldWidth = 3250
  321.     Case FT_BINARY
  322.       GetFieldWidth = 3250
  323.     Case FT_MEMO
  324.       GetFieldWidth = 3250
  325.     Case Else
  326.       GetFieldWidth = 3250
  327.   End Select
  328.  
  329. End Function
  330.  
  331. Function GetNumbRecs (fds As Dynaset) As Long
  332.   Dim ds As Dynaset
  333.  
  334.   On Error GoTo GNRErr
  335.  
  336.   Set ds = fds.Clone()
  337.   If Not ds.EOF Then ds.MoveLast
  338.   GetNumbRecs = ds.RecordCount
  339.   ds.Close
  340.   If fds.Updatable = True Then
  341.     gfUpdatable = True
  342.   End If
  343.  
  344.   GoTo GNREnd
  345.  
  346. GNRErr:
  347.   'just return because row count is non critical
  348.   GetNumbRecs = -1
  349.   Resume GNREnd
  350.  
  351. GNREnd:
  352.  
  353. End Function
  354.  
  355. Function GetNumbRecsSS (fds As Snapshot) As Long
  356.   Dim ds As Snapshot
  357.  
  358.   On Error GoTo GNRSSErr
  359.  
  360.   Set ds = fds.Clone()
  361.   If Not ds.EOF Then
  362.   ds.MoveLast
  363.   End If
  364.   GetNumbRecsSS = ds.RecordCount
  365.   ds.Close
  366.   If fds.Updatable = True Then
  367.     gfUpdatable = True
  368.   End If
  369.  
  370.   GoTo GNRSSEnd
  371.  
  372. GNRSSErr:
  373.   'just return because row count is non critical
  374.   GetNumbRecsSS = -1
  375.   Resume GNRSSEnd
  376.  
  377. GNRSSEnd:
  378.  
  379. End Function
  380.  
  381. Function GetNumbRecsTbl (tbl As Table) As Long
  382.   Dim tbl2 As Table
  383.  
  384.   On Error GoTo GNRTErr
  385.  
  386.   Set tbl2 = tbl.Clone()
  387.   If Not tbl2.EOF Then tbl2.MoveLast
  388.   GetNumbRecsTbl = tbl2.RecordCount
  389.   tbl2.Close
  390.   gfUpdatable = True
  391.  
  392.   GoTo GNRTEnd
  393.  
  394. GNRTErr:
  395.   'just return because row count is non critical
  396.   GetNumbRecsTbl = -1
  397.   Resume GNRTEnd
  398.  
  399. GNRTEnd:
  400.  
  401. End Function
  402.  
  403. '----------------------------------------------------------------------------
  404. 'to use this function in any app,
  405. '1. create a form with a grid
  406. '2. create a dynaset
  407. '3. call this function from the form with
  408. '   grd    = your grid control name
  409. '   dynst$ = your dynaset open string (table name or SQL select statement)
  410. '   numb&  = the max number of rows to load (grid is limited to 2000)
  411. '   start& = starting row (needed to display the record number in the
  412. '            left column when loading blocks of records as the
  413. '            DynaGrid form in this app does with the "More" button)
  414. '----------------------------------------------------------------------------
  415. Function LoadGrid (grd As Control, fds As Snapshot, dynst$, numb&, start&) As Integer
  416.    Dim ft As Integer               'field type
  417.    Dim i As Integer, j As Integer  'for loop indexes
  418.    Dim fn As String                'field name
  419.    Dim rc As Integer               'record count
  420.    Dim gs As String                'grid string
  421.    gsumcolwid = 0' initialize
  422.    On Error GoTo LGErr
  423.  
  424.    MsgBar "Loading Grid for Table View", True
  425.    'setup the grid
  426.    grd.Rows = 2       'reduce the grid
  427.    grd.FixedRows = 0  'allow next step
  428.    grd.Rows = 1       'clears the grid completely
  429.    grd.Cols = fds.Fields.Count + 1
  430.  
  431.    If start& = 0 Then        'only do it on first call
  432.      On Error Resume Next
  433.      'set the column widths
  434.      For i = 0 To fds.Fields.Count - 1
  435.        ft = fds(i).Type
  436.        If ft = FT_STRING Then
  437.          If fds(i).Size > Len(fds(i).Name) Then
  438.            If fds(i).Size <= 10 Then
  439.              grd.ColWidth(i + 1) = fds(i).Size * fQuery.TextWidth("A")
  440.            Else
  441.              grd.ColWidth(i + 1) = 10 * fQuery.TextWidth("A")
  442.            End If
  443.          Else
  444.            If Len(fds(i).Name) <= 10 Then
  445.              grd.ColWidth(i + 1) = Len(fds(i).Name) * fQuery.TextWidth("A")
  446.            Else
  447.              grd.ColWidth(i + 1) = 10 * fQuery.TextWidth("A")
  448.            End If
  449.          End If
  450.        ElseIf ft = FT_MEMO Then
  451.          grd.ColWidth(i + 1) = 1200
  452.        Else
  453.          grd.ColWidth(i + 1) = GetFieldWidth(ft)
  454.        End If
  455.        gsumcolwid = gsumcolwid + grd.ColWidth(i + 1)
  456.      Next
  457.  
  458.      On Error GoTo LGErr
  459.      'load the field names
  460.      grd.Row = 0
  461.      For i = 0 To fds.Fields.Count - 1
  462.        grd.Col = i + 1
  463.        grd.Text = UCase(fds(i).Name)
  464.      Next
  465.    End If
  466.  
  467.    rc = 1
  468.  
  469.    'fill method 1
  470.    'add the rows with the additem method
  471.    While fds.EOF = False And rc <= numb
  472.      gs = CStr(rc + start) + Chr$(9)
  473.      For i = 0 To fds.Fields.Count - 1
  474.        If fds(i).Type = FT_MEMO Then
  475.          If fds(i).FieldSize() < 255 Then
  476.            gs = gs + StripNonAscii(vFieldVal(fds(i))) + Chr$(9)
  477.          Else
  478.            'can only get the 1st 255 chars
  479.            gs = gs + StripNonAscii(vFieldVal(fds(i).GetChunk(0, 255))) + Chr$(9)
  480.          End If
  481.        ElseIf fds(i).Type = FT_STRING Then
  482.          gs = gs + StripNonAscii(vFieldVal(fds(i))) + Chr$(9)
  483.        Else
  484.          gs = gs + vFieldVal(fds(i)) + Chr$(9)
  485.        End If
  486.      Next
  487.      gs = Mid(gs, 1, Len(gs) - 1)
  488.      grd.AddItem gs
  489.      fds.MoveNext
  490.      rc = rc + 1
  491.    Wend
  492.  
  493.    grd.FixedRows = 1   'freeze the field names
  494.    grd.FixedCols = 1   'freeze the row numbers
  495.    grd.Row = 1         'set current position
  496.    grd.Col = 1
  497.  
  498.    LoadGrid = rc       'return number added
  499.    GoTo LGEnd
  500.  
  501. LGErr:
  502.    ShowError
  503.    LoadGrid = False    'return 0
  504.    Resume LGEnd
  505.  
  506. LGEnd:
  507.    MsgBar "", False
  508.  
  509. End Function
  510.  
  511. Sub MsgBar (Msg As String, pw As Integer)
  512.   If Msg = "" Then
  513.     fQuery.Panel3D1.Caption = "Ready"
  514.   Else
  515.     If pw = True Then
  516.       fQuery.Panel3D1.Caption = Msg + ", please wait..."
  517.     Else
  518.       fQuery.Panel3D1.Caption = Msg
  519.     End If
  520.   End If
  521.   fQuery.Panel3D1.Refresh
  522. End Sub
  523.  
  524. Sub Outlines (formname As Form)
  525.     Dim drkgray As Long, fullwhite As Long
  526.     Dim i As Integer
  527.     Dim ctop As Integer, cleft As Integer, cright As Integer, cbottom As Integer
  528.  
  529.     ' Outline a form's controls for 3D look unless control's TAG
  530.     ' property is set to "skip".
  531.  
  532.     Dim cname As Control
  533.     drkgray = RGB(128, 128, 128)
  534.     fullwhite = RGB(255, 255, 255)
  535.  
  536.     For i = 0 To (formname.Controls.Count - 1)
  537.         Set cname = formname.Controls(i)
  538.         If TypeOf cname Is Menu Then
  539.             'Debug.Print "menu item"
  540.         ElseIf (UCase(cname.Tag) = "OL") Then
  541.                 ctop = cname.Top - screen.TwipsPerPixelY
  542.                 cleft = cname.Left - screen.TwipsPerPixelX
  543.                 cright = cname.Left + cname.Width
  544.                 cbottom = cname.Top + cname.Height
  545.                 formname.Line (cleft, ctop)-(cright, ctop), drkgray
  546.                 formname.Line (cleft, ctop)-(cleft, cbottom), drkgray
  547.                 formname.Line (cleft, cbottom)-(cright, cbottom), fullwhite
  548.                 formname.Line (cright, ctop)-(cright, cbottom), fullwhite
  549.         End If
  550.     Next i
  551. End Sub
  552.  
  553. Sub PicOutlines (pic As Control, ctl As Control)
  554.     Dim drkgray As Long, fullwhite As Long
  555.     Dim ctop As Integer, cleft As Integer, cright As Integer, cbottom As Integer
  556.  
  557.     ' Outline a form's controls for 3D look unless control's TAG
  558.     ' property is set to "skip".
  559.  
  560.     Dim cname As Control
  561.     drkgray = RGB(128, 128, 128)
  562.     fullwhite = RGB(255, 255, 255)
  563.  
  564.     ctop = ctl.Top - screen.TwipsPerPixelY
  565.     cleft = ctl.Left - screen.TwipsPerPixelX
  566.     cright = ctl.Left + ctl.Width
  567.     cbottom = ctl.Top + ctl.Height
  568.     pic.Line (cleft, ctop)-(cright, ctop), drkgray
  569.     pic.Line (cleft, ctop)-(cleft, cbottom), drkgray
  570.     pic.Line (cleft, cbottom)-(cright, cbottom), fullwhite
  571.     pic.Line (cright, ctop)-(cright, cbottom), fullwhite
  572.  
  573. End Sub
  574.  
  575. Sub RefreshTables (tbl_list As Control, IncludeQueries As Integer)
  576.    Dim i As Integer, j As Integer, h As Integer
  577.    Dim st As String
  578.    Dim OkayToAdd As Integer
  579.  
  580.    On Error GoTo TRefErr
  581.    IncludeQueries = False
  582.    gstDataType = "MS Access"
  583.    Set gTableListSS = gCurrentDB.ListTables()
  584.    tbl_list.Clear
  585.  
  586.    If IncludeQueries And gstDataType = "MS Access" Then
  587.      ' the ListTables method is used to display querydefs that might
  588.      ' be present in an Access database, see below for optional code
  589.      While gTableListSS.EOF = False
  590.        st = gTableListSS!Name
  591.          If (gTableListSS!Attributes And DB_SYSTEMOBJECT) = 0 Then
  592.            tbl_list.AddItem st
  593.          End If
  594.        gTableListSS.MoveNext
  595.      Wend
  596.    Else
  597.      ' this method uses the tabledefs collection but will not display
  598.      ' querydefs in an Access database
  599.      tbl_list.Clear
  600.      For i = 0 To gCurrentDB.TableDefs.Count - 1
  601.        st = gCurrentDB.TableDefs(i).Name
  602.        If (gCurrentDB.TableDefs(i).Attributes And DB_SYSTEMOBJECT) = 0 Then
  603.             If UCase(Left(st, 4)) = "DBO." Then
  604.                 st = Mid(st, 5, Len(st))
  605.             End If
  606.          tbl_list.AddItem st
  607.        End If
  608.      Next
  609.    End If
  610.   
  611.    GoTo TRefEnd
  612.  
  613. TRefErr:
  614.    ShowError
  615.    gfDBOpenFlag = False
  616.    Resume TRefEnd
  617.  
  618. TRefEnd:
  619.  
  620. End Sub
  621.  
  622. Sub resetdefault ()
  623. Dim deselect As Integer
  624. For deselect = 0 To fQuery!cTableList.ListCount - 1
  625.         If fQuery!cTableList.Selected(deselect) Then
  626.             fQuery!cTableList.Selected(deselect) = False
  627.         End If
  628.     Next deselect
  629.   deselect = 0
  630.   fQuery!cShowFields.Clear
  631.   fQuery.cJoinFields.Clear
  632.   If Not fQuery!cColOrder.ListIndex Then
  633.   fQuery!cColOrder.ListIndex = 0
  634.   fQuery!cOrderByField.ListIndex = 0
  635.   End If
  636.   fQuery!cField.Clear
  637.   fQuery!cValue.Clear
  638.   fQuery!cCriteria = ""
  639.   fQuery!CriteriaLabel.Caption = "SQL Statement"
  640.   fQuery!RunSaveQryButton.Caption = "&Load Query"
  641.   fQuery!RunSaveQryButton.Enabled = True
  642.   fQuery!ExecSqlButton.Enabled = True
  643.   gFilterStr = ""
  644.   gSortStr = ""
  645.   gStoredFlag = False
  646.   gfFROMSQL = False
  647.   fQuery.Tag = ""
  648.   gstDynaString = ""
  649.   MsgBar "", False
  650. End Sub
  651.  
  652. Sub ResetMouse (f As Form)
  653.   fQuery.MousePointer = DEFAULT_MOUSE
  654.   f.MousePointer = DEFAULT_MOUSE
  655. End Sub
  656.  
  657. Function SetFldProperties (ft As String) As String
  658.   'return field length
  659.   If ft = "String" Then
  660.     gwFldType = FT_STRING
  661.   Else
  662.     Select Case ft
  663.       Case "Counter"
  664.         SetFldProperties = "4"
  665.         gwFldType = FT_LONG
  666.         gwFldSize = 4
  667.       Case "True/False"
  668.         SetFldProperties = "1"
  669.         gwFldType = FT_TRUEFALSE
  670.         gwFldSize = 1
  671.       Case "Byte"
  672.         SetFldProperties = "1"
  673.         gwFldType = FT_BYTE
  674.         gwFldSize = 1
  675.       Case "Integer"
  676.         SetFldProperties = "2"
  677.         gwFldType = FT_INTEGER
  678.         gwFldSize = 2
  679.       Case "Long"
  680.         SetFldProperties = "4"
  681.         gwFldType = FT_LONG
  682.         gwFldSize = 4
  683.       Case "Currency"
  684.         SetFldProperties = "8"
  685.         gwFldType = FT_CURRENCY
  686.         gwFldSize = 8
  687.       Case "Single"
  688.         SetFldProperties = "4"
  689.         gwFldType = FT_SINGLE
  690.         gwFldSize = 4
  691.       Case "Double"
  692.         SetFldProperties = "8"
  693.         gwFldType = FT_DOUBLE
  694.         gwFldSize = 8
  695.       Case "Date/Time"
  696.         SetFldProperties = "8"
  697.         gwFldType = FT_DATETIME
  698.         gwFldSize = 8
  699.       Case "Binary"
  700.         SetFldProperties = "0"
  701.         gwFldType = FT_BINARY
  702.         gwFldSize = 0
  703.       Case "Memo"
  704.         SetFldProperties = "0"
  705.         gwFldType = FT_MEMO
  706.         gwFldSize = 0
  707.     End Select
  708.   End If
  709. End Function
  710.  
  711. Sub SetHourGlass (f As Form)
  712.   DoEvents  'cause forms to repaint before going on
  713.   fQuery.MousePointer = HOURGLASS
  714.   f.MousePointer = HOURGLASS
  715. End Sub
  716.  
  717. Sub ShowError ()
  718.   Dim s As String
  719.   Dim crlf As String
  720.  
  721.   crlf = Chr(13) + Chr(10)
  722.   s = "The following Error occurred:" + crlf + crlf
  723.   'add the error string
  724.   s = s + Error$ + crlf
  725.   'add the error number
  726.   s = s + "Number: " + CStr(Err)
  727.   'beep and show the error
  728.   Beep
  729.   MsgBox (s)
  730.  
  731. End Sub
  732.  
  733. Sub ShowHelp (PBtn As Control, px As Single, py As Single)
  734. ' Subroutine to show popup help for a control
  735. ' To use:
  736. '    add a panel control called PnlHelp to the form
  737. '    Set control's tag property to help message desired
  738. '    Copy this subroutine to the form code and uncomment code below
  739. '    In mousemove event of control add
  740. '       ShowHelp control-name, x, y
  741. '    In click event or other events of control that cause action add
  742. '       ShowHelp control-name, 0, 0     ' Hides help
  743.  
  744.     Dim maxx As Single, maxy As Single
  745.     Dim nPnlTop As Single, nPnlLeft As Single
  746.     ' Determine max x & y coordinates with 80 twip border
  747.     ' boundry of 80 twips allowed to be able to catch cursor as exiting control
  748.     maxx = PBtn.Width - 80
  749.     maxy = PBtn.Height - 80
  750.     ' if exiting control area turn off help panel
  751.     If px < 80 Or py < 80 Or px > maxx Or py > maxy Then
  752.         fQuery!PnlHelp.Visible = False
  753.         fQuery!PnlHelp.Caption = ""
  754.         Exit Sub
  755.     End If
  756.  
  757.     ' Determine location for help panel
  758.     ' Assume below and to right
  759.     nPnlTop = PBtn.Top + PBtn.Height + 40
  760.     nPnlLeft = PBtn.Left + 100
  761.     ' Put panel above control if not enough room below
  762.     If nPnlTop + fQuery!PnlHelp.Height > fQuery!PnlHelp.Height - 1024 Then
  763.         nPnlTop = PBtn.Top - fQuery!PnlHelp.Height - 40
  764.     End If
  765.     ' Put panel to left if not enough room to right
  766.     If nPnlLeft + fQuery!PnlHelp.Width > fQuery!PnlHelp.Width - 500 Then
  767.         nPnlLeft = PBtn.Left + PBtn.Width - 40
  768.     End If
  769.  
  770.     ' if same settings exit to prevent flickering effect
  771.     If fQuery!PnlHelp.Caption = PBtn.Tag And fQuery!PnlHelp.Top = nPnlTop And fQuery!PnlHelp.Left = nPnlLeft Then
  772.         Exit Sub
  773.     End If
  774.     
  775.     ' get help msg from control's tag and position help panel
  776.     fQuery!PnlHelp.Caption = PBtn.Tag
  777.     fQuery!PnlHelp.Top = nPnlTop
  778.     fQuery!PnlHelp.Left = nPnlLeft
  779.     fQuery!PnlHelp.Visible = True
  780.     
  781. End Sub
  782.  
  783.     Function StringfromPrivINI (Sectionname As String, Keyname As String, Default As String, Filename As String) As String
  784. 'Function reads an item from an app's INI file.
  785. '   -SectionName is the Application name
  786. '   -KeyName is the Key to read from the ini file
  787. '   -Default is the value to be supplied if the ini file doesn't exist or if the key
  788. '       hasn't been created/defined in the INI file.
  789. '   -ReturnedString is the string read from the INI file
  790. '   -ReturnedStringLen is the max allowable length of ReturnedString
  791. '   -FileName is the INI file name.
  792. '
  793. 'ALL OF THESE PARAMETERS MUST BE INITIALIZED for this API call to work.
  794.     Dim Resultstr As String
  795.     Dim ReturnedStr As String
  796.     Dim StringfromPrivateINI As String
  797.     Dim MaxStringLen As Integer
  798.     Dim Result  As Integer
  799.  
  800.     MaxStringLen = 400
  801.     ReturnedStr = Space(MaxStringLen)
  802.  
  803.     Result = GetPrivateProfileString(Sectionname, Keyname, Default, ReturnedStr, MaxStringLen, Filename$)
  804.     Resultstr = LTrim(RTrim$(ReturnedStr)) ' TRIM OUT BLANKS
  805.     Resultstr = Left(Resultstr, Len(Resultstr) - 1) ' REMOVE CHR$(0) FROM END
  806.     StringfromPrivINI = Resultstr
  807.  
  808. End Function
  809.  
  810. Function StringtoPrivINI (Sectionname As String, Keyname As String, lpDefault As String, Filenamein As String)
  811. StringtoPrivINI = WritePrivateProfileString(Sectionname, Keyname, lpDefault, Filenamein)
  812. End Function
  813.  
  814. Function StripFileName (fname As String) As String
  815.   On Error Resume Next
  816.   Dim i As Integer
  817.  
  818.   For i = Len(fname) To 1 Step -1
  819.     If Mid(fname, i, 1) = "\" Then
  820.       Exit For
  821.     End If
  822.   Next
  823.  
  824.   StripFileName = Mid(fname, 1, i - 1)
  825.  
  826. End Function
  827.  
  828. Function StripNonAscii (vs As Variant) As String
  829.   Dim i As Integer
  830.   Dim ts As String
  831.  
  832.   For i = 1 To Len(vs)
  833.     If Asc(Mid(vs, i, 1)) < 32 Or Asc(Mid(vs, i, 1)) > 126 Then
  834.       ts = ts + " "
  835.     Else
  836.       ts = ts + Mid(vs, i, 1)
  837.     End If
  838.   Next
  839.  
  840.   StripNonAscii = ts
  841.  
  842. End Function
  843.  
  844. Function stTrueFalse (tf As Variant) As String
  845.   If tf = True Then
  846.     stTrueFalse = "True"
  847.   Else
  848.     stTrueFalse = "False"
  849.   End If
  850. End Function
  851.  
  852. Function TableType (tbl As String) As Integer
  853.   Dim i As Integer
  854.  
  855.   gTableListSS.MoveFirst
  856.   While gTableListSS.EOF = False And gTableListSS!Name <> tbl
  857.     gTableListSS.MoveNext
  858.   Wend
  859.   If gTableListSS!Name = tbl Then
  860.     TableType = gTableListSS!TableType
  861.   Else
  862.     TableType = 0
  863.   End If
  864.  
  865. End Function
  866.  
  867. Function vFieldVal (fval As Variant) As Variant
  868.   If IsNull(fval) Then
  869.     vFieldVal = ""
  870.   Else
  871.     vFieldVal = CStr(fval)
  872.   End If
  873. End Function
  874.  
  875. Function WinDir$ ()
  876. 'Author:            Barry Seymour, Vanguard Business Solutions
  877. 'Date:              29Aug91
  878. 'Globals used:      None
  879. 'Functions Called:  GetgWindowsDirectory, defined in GLOBAL.BAS as follows:
  880. '--------------------------------------------------------------------------------------------------------------
  881. 'Declare Function GetgWindowsDirectory Lib "Kernel" (ByVal lpBuffer As String, ByVal nSize As Integer) As Integer
  882. '---------------------------------------------------------------------------------------------------------------
  883.  
  884. 'Explanation:   This Function returns a string containing the
  885. '               name of the Windows directory.  The GetgWindowsDirectory
  886. '               function call is defined in GLOBAL.BAS (see above)
  887. '               and uses a Windows API call to the Kernel.
  888.  
  889. ' IMPORTANT NOTE:   The string to contain the returned data MUST be fully
  890. ' initialized prior to placing data in it, else an Unrecoverable
  891. ' Application Error (UAE) will result.  This Function initializes the
  892. ' string with empty spaces so the result can be trimmed.
  893. ' EVEN SO, the result string has a null char at the end of it which
  894. ' must be stripped away manually - RTrim$ or LTrim$ don't strip out
  895. ' null chars.
  896. '
  897. ' ANOTHER IMPORTANT NOTE:  If your windows directory is in the ROOT, a
  898. ' backslash is at the end of the string ("C:\").  If not, there is no
  899. ' backslash at the end of the string ("c:\WIN").
  900.  
  901. 'Error trapping is also in this code, giving a STERN WARNING to the user.
  902. 'If this procedure fails, your system is mightily confused.
  903. '----------------------------------------------------------------------------
  904.     Dim lf As String
  905.     Dim WindowsPathName As String
  906.     Dim Msg  As String
  907.     Dim PathStringLength, Success As Integer
  908.  
  909.     
  910.     lf = Chr(13) + Chr(10)  'linefeed for message formatting
  911.     
  912.     PathStringLength = 255 'The length is arbitrary, but MUST be defined.
  913.     
  914.     WindowsPathName = String(PathStringLength, " ")
  915.     'Initialize the full string to SPACES.  The full length of the
  916.     'string MUST be present before making the function call, else UAE!
  917.     
  918.     Success = GetWindowsDirectory(WindowsPathName, PathStringLength)
  919.     If Success Then
  920.         WinDir$ = Left$(RTrim$(WindowsPathName), Len(RTrim$(WindowsPathName)) - 1)
  921.         '                   |--Trim trailing blanks   |-Trim null char at end of string.
  922.     Else
  923.         WinDir = "c:\WIN"
  924.         Msg = "SYSTEM ERROR: Unable to determine Windows Directory." + lf
  925.         If Err <> 0 Then
  926.             Msg = Msg + "Error " + Str$(Err) + ":" + lf
  927.             Msg = Msg + Error$(Err) + "." + lf
  928.         Else
  929.             Msg = Msg + lf + "Error Number Unknown." + lf
  930.         End If
  931.         Msg = Msg + "Assuming Windows Directory to be c:\WIN." + lf + lf
  932.         Msg = Msg + "It is STRONGLY RECOMMENDED that you save your work " + lf
  933.         Msg = Msg + "and SHUT DOWN this application."
  934.         Beep: Beep: Beep: MsgBox Msg, 16, "System Error"
  935.     End If
  936. End Function
  937.  
  938.